﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace PDX.ChangeTracking
{
    /// <summary>
    /// Tracks an <see cref="Editor"/> and reports <see cref="Snapshot"/>s
    /// to an <see cref="ISnapshotHandler"/>.
    /// </summary>
    public class SnapshotReporter
    {
        /// <summary>
        /// Gets the <see cref="Editor"/> changes are being tracked on.
        /// </summary>
        protected Editor Target { get; private set; }

        /// <summary>
        /// Gets the <see cref="ISnapshotHandler"/> to report changes to.
        /// </summary>
        protected ISnapshotHandler Handler { get; private set; }

        System.Windows.IInputElement lastFocus;

        /// <summary>
        /// Initializes a new instance of the <see cref="SnapshotReporter"/> class.
        /// </summary>
        /// <param name="editor">The editor.</param>
        /// <param name="recorder">The recorder.</param>
        public SnapshotReporter(Editor editor, ISnapshotHandler recorder)
        {
            this.Target = editor;
            this.Handler = recorder;

            editor.GotKeyboardFocus += new System.Windows.Input.KeyboardFocusChangedEventHandler(editor_GotKeyboardFocus);
            editor.LostKeyboardFocus += new System.Windows.Input.KeyboardFocusChangedEventHandler(editor_LostKeyboardFocus);
        }

        void editor_GotKeyboardFocus(object sender, System.Windows.Input.KeyboardFocusChangedEventArgs e)
        {
            var pm = Context.GetPropertyModel(Target) as IPropertyModel;
            if (pm != null)
            {
                lastFocus = e.NewFocus;
                Report();

                // TODO - if we go off an injected INotificationManager, we might
                // be doing extra work. Going off the propertymodel's PropertyChanged
                // seems to be working for now. Maybe think about this more.
                pm.PropertyChanged += pm_PropertyChanged;
            }
        }

        void pm_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            Report();
        }

        void editor_LostKeyboardFocus(object sender, System.Windows.Input.KeyboardFocusChangedEventArgs e)
        {
            var pm = Context.GetPropertyModel(Target) as IPropertyModel;
            if (pm != null)
            {
                pm.PropertyChanged -= pm_PropertyChanged;
                lastFocus = e.OldFocus;

                Report();
            }
        }

        void Report()
        {
            var pm = Context.GetPropertyModel(Target) as IPropertyModel;
            if (pm != null)
            {
                var value = pm.Value;
                var snap = Snapshot.Create(pm, Target, value, lastFocus);
                Handler.Handle(snap);
            }
        }
    }
}
